/*
 * Copyright (c) 2011 Imre Fazekas.
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of the Brillien nor the names of its
 * terms and concepts may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.vii.streamline.structures.collections;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.LinkedList;

/**
 * Special list type to handle collection-based operations. 
 */
public class InnerList<V> extends LinkedList<V> {


    public InnerList() {
    }

    /*
    public InnerList( V v, V[] wss ){
        add( v );
        for( V vs : wss )
            if( !contains(vs) ) add( vs );
    }
    */

    /**
     * Constructs a new Innerlist by by copying the references from two arrays
     * @param vs source array 1
     * @param ws source array 2
     */
    public InnerList( V[] vs, V[] ws ){
        if( vs != null )
        for( V v : vs )
            add( v );
        if( ws != null )
        for( V v : ws )
            if( !contains(v) ) add( v );
    }

    /**
     * Constructs a new Innerlist by copying the references from two iterable instances
     * @param vs source iterable instance 1
     * @param ws source iterable instance 2
     */
    public InnerList( Iterable<V> vs, Iterable<V> ws ){
        if( vs != null )
        for( V v : vs )
            add( v );
        if( ws != null )
        for( V v : ws )
            if( !contains(v) ) add( v );
    }

    /**
     * Constructs a new Innerlist by copying the references from an iterable instance
     * @param vs source iterable instance
     */
    public InnerList( Iterable<V> vs ){
        if( vs != null )
        for( V v : vs )
            add( v );
    }

    /**
     * Constructs a new Innerlist by copying the references from an array
     * @param vs source array
     */
    public InnerList( V... vs ){
        if( vs != null )
        for( V v : vs )
            add( v );
    }

    /**
     * Constructs a new Innerlist by copying the references from a collection
     * @param vs source collection
     */
    public InnerList( Collection<V> vs ){
        if( vs != null )
        for( V v : vs )
            add( v );
    }

    public InnerList add( V... vs ){
        if( vs != null )
        for( V v : vs )
            add( v );
        return this;
    }

    public InnerList add( Iterable<V> vs ){
        if( vs != null )
        for( V v : vs )
            add( v );
        return this;
    }
    
    /**
     * Gets the set of the elements as a Seriable array
     */
    public Object[] asArray( ){
        return toArray(
            new Object[ size() ]
        );
    }

    /**
     * Gets the set of the elements as a Seriable array 
     */
    public V[] asArray( Class<V> c ){
        return toArray(
            (V[])Array.newInstance( c, size() )
        );
    }
}
